home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / net / bind-contrib.tar.gz / bind-contrib.tar / contrib / ckdns / ckdns.shar / ckserial.sh < prev   
Encoding:
Linux/UNIX/POSIX Shell Script  |  1996-10-25  |  5.0 KB  |  237 lines

  1. #!/bin/sh
  2. # @(#)ckserial.sh    1.4    11/21/90
  3. #
  4. # ckserial - check zone file serial numbers
  5. #
  6. # ckserial checks the serial numbers of zone files to ensure
  7. # that they are sequenced properly.  It keeps a checkpointed
  8. # set of data for comparison purposes.
  9. #
  10. # USAGE
  11. #    ckserial [ bootfile ]
  12. #
  13. # BUGS
  14. #    Assumes optional ttl field for SOA record is not used.
  15.  
  16. BOOTFILE=/etc/named.boot
  17. CKPTDIR=ckpoint        # relative to 'directory' in bootfile
  18. LOGFILE=/tmp/.ckslog$$
  19. SEDFILE=/tmp/.ckssed$$
  20. MAIL=/usr/ucb/Mail
  21. NOTIFY=hostmaster
  22.  
  23. # change default bootfile if necessary
  24. if [ "$1" != "" ]; then
  25.     if [ -f $1 ]; then
  26.         BOOTFILE=$1
  27.     else
  28.         echo usage: `basename $0` "[ bootfile ]"
  29.         exit 1
  30.     fi
  31. fi
  32.  
  33. trap "rm -f /tmp/.cks*$$; exit 1" 2 3
  34.  
  35. # sed file for massaging zone data
  36. cat >$SEDFILE <<!
  37. /^;/d
  38. s/;.*//
  39. :join
  40. /([^)]*$/N
  41. s/\n[     ]*/ /
  42. t join
  43. s/(\(.*\))/\1/
  44. !
  45.  
  46. # strip comments from zone data
  47. stripcomments() {
  48.     sed -e '/^;/d' -e 's/;.*//' $*
  49. }
  50.  
  51. # list zone files used by boot file
  52. #  secondary zones are not checked.  These are assumed to be correct
  53. #  as far as transfers go because old serial numbers won't (shouldn't)
  54. #  be transferred.  Besides, I'm not sure of the semantics for determining
  55. #  whether the last entry is a file or not.  I suppose a simple test of
  56. #  existence would work though.
  57. getzonefiles() {
  58.     awk '\
  59.     $1 == "cache" || $1 == "CACHE" || \
  60.     $1 == "primary" || $1 == "PRIMARY" {
  61.         printf "%s\n",$NF }' $1
  62. }
  63.  
  64. # get zone file directory
  65. getzonedir() {
  66.     stripcomments $1 | awk 'BEGIN { dir = "/"; }
  67.     $1 == "directory" || $1 == "DIRECTORY" {
  68.         dir = $2 }
  69.     END {print dir}'
  70. }
  71.  
  72. # get SOA serial number
  73. getserialnumber() {
  74.     tr a-z A-Z <$1 | sed -f $SEDFILE | awk '$3 == "SOA" { print $6}'
  75. }
  76.  
  77. # get mail address of person in charge of the zone
  78. getpersonincharge() {
  79.     stripcomments $1 | tr a-z A-Z | awk '$3 == "SOA" {print $5}'
  80. }
  81.  
  82. # get zone origin
  83. getzone() {
  84.     # get zone from zone data file
  85.     zone=`stripcomments $1 | tr a-z A-Z | awk '$3 == "SOA" {print $1}'`
  86.     # if zone is current origin
  87.     if [ "$zone" = "@" ]; then
  88.         # get zone from bootfile
  89.         zone=`grep $1 $BOOTFILE | awk '{print $2}'`
  90.     fi
  91.     echo $zone
  92. }
  93.  
  94. # checkpoint a list of files
  95. checkpoint() {
  96.     while [ "$1" != "" ]; do
  97.         # copy file preserving modes/dates
  98.         cp -p $1 $CKPTDIR/$1
  99.         shift
  100.     done
  101. }
  102.  
  103. # get list of include files from zone file
  104. includefiles() {
  105.     grep -i '^\$include' $1 | awk '{print $2}'
  106. }
  107.  
  108. # is arg 1 < arg2
  109. #  test integer and floating numbers
  110. lt() {
  111.     awk 'BEGIN{ if ('$1' < '$2') exit 0; else exit 1; }'
  112. }
  113.  
  114. # compare two files ignoring white space changes
  115. compare() {
  116.     diff -b $1 $2 >/dev/null
  117. }
  118.  
  119. # log a zonefile error message
  120. errlog() {
  121.     ERRORFILE=$1    # save zone file for error reporting
  122.     echo "$2" 1>&2
  123.     echo "$2" >>$LOGFILE
  124. }
  125.  
  126. # convert domain name to mail address
  127. domaintoaddr() {
  128.     echo $1 | sed -e 's/\.$//' -e 's/\./@/'
  129. }
  130.  
  131. # notify the person in charge of a zone of detected errors
  132. notifypersonincharge() {
  133.     MB=`getpersonincharge $1`
  134.     ZONE=`getzone $1`
  135.     $MAIL -s "$ZONE zone configuration error" $NOTIFY `domaintoaddr $MB` <$LOGFILE
  136.     echo "    $NOTIFY, `domaintoaddr $MB` notified via mail."
  137. }
  138.  
  139. processerrors() {
  140.     # if errors found, notify person in charge
  141.     if [ -f $LOGFILE ]; then
  142.         notifypersonincharge $ERRORFILE
  143.  
  144.         # truncate error log file
  145.         rm -f $LOGFILE
  146.     fi
  147. }
  148.  
  149. #########################
  150. # real work starts here #
  151. #########################
  152.  
  153. # cd to the zone file data directory
  154. cd `getzonedir $BOOTFILE`
  155.  
  156. ZONEFILES=`getzonefiles $BOOTFILE`
  157. SOAFILES=`grep -il '[     ]IN[     ]*SOA[     ]' $ZONEFILES | stripcomments`
  158. EXIT=0
  159.  
  160. for f in $SOAFILES; do
  161.     # process any logged errors
  162.     processerrors
  163.  
  164.     # check for zone file existence
  165.     if [ ! -f $f ]; then
  166.         echo "$BOOTFILE: $f doesn't exist" 1>&2
  167.         continue
  168.     fi
  169.  
  170.     # if this zone file is new, checkpoint it
  171.     if [ ! -f $CKPTDIR/$f ]; then 
  172.         checkpoint $f
  173.         continue
  174.     fi
  175.  
  176.     #get serial number of current version
  177.     nserialno=`getserialnumber $f`
  178.  
  179.     #get serial number of checkpointed version
  180.     oserialno=`getserialnumber $CKPTDIR/$f`
  181.  
  182.     #if serial number differs, continue
  183.     if [ $nserialno != $oserialno ]; then
  184.         # sanity check first
  185.         if lt $nserialno $oserialno; then
  186.             errlog $f "$f: serial number ($nserialno) < previous ($oserialno)"
  187.             EXIT=1
  188.             continue
  189.         fi
  190.  
  191.         # checkpoint new zone file and included files
  192.         checkpoint $f `includefiles $f`
  193.         continue
  194.     fi
  195.  
  196.     #if file differs from ckpoint - error
  197.     if compare $f $CKPTDIR/$f; then
  198.         : all ok
  199.     else
  200.         errlog $f "$f: zone file changed, but serial number didn't"
  201.         EXIT=1
  202.         continue
  203.     fi
  204.  
  205.     # test included files as well
  206.     for i in `includefiles $f`; do
  207.         # if this zone file is new, checkpoint it
  208.         if [ ! -f $CKPTDIR/$i ]; then 
  209.             checkpoint $i
  210.             continue
  211.         fi
  212.  
  213.         #if file differs from ckpoint - error
  214.         if compare $i $CKPTDIR/$i; then
  215.             : all ok
  216.         else
  217.             errlog $f "$f included changed zone data from $i, but serial number didn't change"
  218.             EXIT=1
  219.             continue
  220.         fi
  221.  
  222.         # check for nested includes.  these aren't handled
  223.         # but we don't expect them either.
  224.         if [ "`grep -i '\$include' $i`" != "" ]; then
  225.             errlog $i "include file $i includes other files."
  226.             EXIT=1
  227.         fi
  228.     done
  229. done
  230.  
  231. # process any remaining errors
  232. processerrors
  233.  
  234. rm -f /tmp/.cks*$$
  235.  
  236. exit $EXIT
  237.